package com.lefevre.cms.service.staff.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lefevre.cms.bean.QueryResult;
import com.lefevre.cms.bean.staff.StaffLoginLog;
import com.lefevre.cms.bean.staff.SysPermission;
import com.lefevre.cms.bean.staff.SysUsers;
import com.lefevre.cms.bean.staff.SysUsersRoles;
import com.lefevre.cms.mapper.StaffLoginLogMapper;
import com.lefevre.cms.mapper.SysPermissionMapper;
import com.lefevre.cms.mapper.SysUsersMapper;
import com.lefevre.cms.mapper.SysUsersRolesMapper;
import com.lefevre.cms.service.besa.DaoSupport;
import com.lefevre.cms.service.staff.ACLService;
import com.lefevre.cms.service.staff.StaffService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 员工管理
 *
 * @author Lefevre
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class StaffServiceImpl extends DaoSupport implements StaffService {
    private static final Logger logger = LoggerFactory.getLogger(StaffServiceImpl.class);
    @Resource
    ACLService aclService;
    @Resource
    private SysUsersMapper sysUsersMapper;
    @Resource
    private SysPermissionMapper sysPermissionMapper;
    @Resource
    private SysUsersRolesMapper sysUsersRolesMapper;
    @Resource
    private StaffLoginLogMapper staffLoginLogMapper;

    /**
     * 得到用户权限
     *
     * @param userAccount 用户账号
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<GrantedAuthority> loadUserAuthoritiesByName(String userAccount) {
        try {
            List<GrantedAuthority> auths = new ArrayList<>();
            List<String> authorities = loadUserAuthorities(userAccount);
            if (authorities != null && authorities.size() > 0) {
                for (String roleName : authorities) {
                    auths.add(new SimpleGrantedAuthority(roleName));
                }
            }
            return auths;
        } catch (RuntimeException re) {
            logger.error("得到用户权限", re);
            throw re;
        }
    }

    /**
     * 得到所有权限
     *
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<GrantedAuthority> loadAllAuthorities() {
        try {
            List<GrantedAuthority> auths = new ArrayList<>();
            List<SysPermission> sysPermissionList = aclService.findPermissionList();
            if (sysPermissionList != null && sysPermissionList.size() > 0) {
                for (SysPermission permission : sysPermissionList) {
                    auths.add(new SimpleGrantedAuthority(permission.getName()));
                }
            }
            return auths;
        } catch (RuntimeException re) {
            logger.error("得到所有权限", re);
            throw re;
        }
    }

    /**
     * 根据用户名称得到用户角色Id
     *
     * @param userAccount 用户账号
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<String> findRoleIdByUserAccount(String userAccount) {
        return sysUsersRolesMapper.selectRoleIdsByUser(userAccount);
    }

    /**
     * 根据用户账号取得权限名称
     *
     * @param userAccount 用户账号
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<String> loadUserAuthorities(String userAccount) {
        return sysPermissionMapper.selectPermissionNamesByUser(userAccount);
    }

    /**
     * 根据用户账号取得权限Id
     *
     * @param userAccount 用户账号
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<String> findPermissionIdByUserAccount(String userAccount) {
        return sysPermissionMapper.selectPermissionIdsByUser(userAccount);
    }

    /**
     * 根据用户账号返回SysUsers实例对象。
     *
     * @param userAccount 用户账号，比如admin等。
     * @return SysUsers实例对象。
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public SysUsers findByUserAccount(String userAccount) {
        return sysUsersMapper.selectOne(new LambdaQueryWrapper<SysUsers>().eq(SysUsers::getUserAccount, userAccount));
    }

    /**
     * 根据员工名称查询员工安全摘要
     *
     * @param userName 用户名称
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public String findSecurityDigestByStaffName(String staffName) {
        return sysUsersMapper.selectOne(new LambdaQueryWrapper<SysUsers>()
                .select(SysUsers::getSecurityDigest)
                .eq(SysUsers::getUserAccount, staffName)).getSecurityDigest();
    }

    /**
     * 保存员工
     *
     * @param sysUsers         用户
     * @param sysUsersRoleList 用户角色
     */
    public void saveUser(SysUsers sysUsers, Set<SysUsersRoles> sysUsersRoleList) {
        if (sysUsersRoleList != null && sysUsersRoleList.size() > 0) {
            for (SysUsersRoles sysUsersRoles : sysUsersRoleList) {
                sysUsersRolesMapper.insert(sysUsersRoles);
            }
        }
        sysUsersMapper.insert(sysUsers);
    }

    /**
     * 删除员工角色
     *
     * @param userAccount 用户账号
     */
    private void deleteUsersRoles(String userAccount) {
        if (userAccount != null && !"".equals(userAccount)) {
            sysUsersRolesMapper.delete(new LambdaUpdateWrapper<SysUsersRoles>().eq(SysUsersRoles::getUserAccount, userAccount));
        }
    }

    /**
     * 修改员工
     *
     * @param sysUsers      用户
     * @param usersRoleList 用户角色
     */
    public void updateUser(SysUsers sysUsers, Set<SysUsersRoles> usersRoleList) {
        //修改员工
        this.update(sysUsers);
        //删除用户角色
        deleteUsersRoles(sysUsers.getUserAccount());
        //保存用户角色
        if (usersRoleList != null && usersRoleList.size() > 0) {
            for (SysUsersRoles sysUsersRoles : usersRoleList) {
                sysUsersRolesMapper.insert(sysUsersRoles);
            }
        }
    }

    /**
     * 删除员工
     *
     * @param staffId     员工Id
     * @param userAccount 用户账号
     */
    public void deleteUser(String staffId, String userAccount) {
        if (userAccount != null && !"".equals(userAccount)) {
            sysUsersRolesMapper.delete(new LambdaUpdateWrapper<SysUsersRoles>().eq(SysUsersRoles::getUserAccount, userAccount));
            //删除员工角色
            this.deleteUsersRoles(userAccount);
            //删除员工日志
            this.deleteStaffLoginLog(staffId);
        }
    }

    /**----------------------------------- 员工登录日志 -------------------------------------**/


    /**
     * 保存员工登录日志
     * 先由staffLoginLogManage.createStaffLoginLogObject();方法生成对象再保存
     *
     * @param staffLoginLog 员工登录日志
     */
    public void saveStaffLoginLog(Object staffLoginLog) {
        staffLoginLogMapper.insert((StaffLoginLog) staffLoginLog);
    }

    /**
     * 删除员工登录日志
     *
     * @param staffId 员工Id
     */
    private Integer deleteStaffLoginLog(String staffId) {
        return staffLoginLogMapper.delete(new LambdaUpdateWrapper<StaffLoginLog>().eq(StaffLoginLog::getStaffId, staffId));
    }

    /**
     * 员工登录日志分页
     *
     * @param staffId    员工Id
     * @param firstIndex 索引开始,即从哪条记录开始
     * @param maxResult  获取多少条数据
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<StaffLoginLog> findStaffLoginLogPage(String staffId, int firstIndex, int maxResult) {
        QueryResult<StaffLoginLog> qr = new QueryResult<>();

        LambdaQueryWrapper<StaffLoginLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StaffLoginLog::getStaffId, staffId);
        Page<StaffLoginLog> staffLoginLogPage = staffLoginLogMapper.selectPage(new Page<>(firstIndex, maxResult), wrapper);

        qr.setResultlist(staffLoginLogPage.getRecords());
        qr.setTotalrecord(staffLoginLogPage.getTotal());
        return qr;
    }

}
